package com.ermax.aircond.report.web.bean;

import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickUnit;
import org.jfree.chart.axis.DateTickUnitType;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.Hour;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.ermax.aircond.common.domain.ReadMachineDataAudit;
import com.ermax.aircond.common.parameter.Status;
import com.ermax.aircond.common.service.ReadMachineDataService;
import com.ermax.aircond.maintain.domain.Building;
import com.ermax.aircond.maintain.domain.Floor;
import com.ermax.aircond.maintain.domain.Machine;
import com.ermax.aircond.maintain.domain.Room;
import com.ermax.aircond.maintain.service.MaintainService;
import com.ermax.aircond.report.service.AuditLogService;
import com.ermax.aircond.resource.MessageBundle;
import com.ermax.aircond.util.service.MachineCommandService;
import com.ermax.aircond.util.web.bean.DataTableBean;

@Scope("view")
@Component
public class SlaveDataAuditLogBean extends DataTableBean implements java.io.Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static final DateFormat DATA_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
	private static final Logger logger = LoggerFactory.getLogger(SlaveDataAuditLogBean.class);

	@Resource(name = "maintainService")
	private MaintainService maintainService;

	@Resource(name = "auditLogService")
	private AuditLogService auditLogService;

	@Resource(name = "readMachineDataService")
	private ReadMachineDataService readMachineDataService;

	@Resource(name = "machineCommandService")
	private MachineCommandService machineCommandService;

	private Date searchFromDate = new Date();
	private Date searchToDate = new Date();

	private long selectedBuildingId;
	private long selectedFloorId;
	private long selectedRoomId;
	private long selectedMachineId;
	private List<SelectItem> buildingOptions = new ArrayList<SelectItem>();
	private List<SelectItem> floorOptions = new ArrayList<SelectItem>();
	private List<SelectItem> roomOptions = new ArrayList<SelectItem>();
	private List<SelectItem> machineOptions = new ArrayList<SelectItem>();

	private boolean showChart = false;
	private Locale lastLocale = Locale.ENGLISH;

	@PostConstruct
	public void init() {
		try {
			reset();
		} catch (Exception ex) {
			String message = MessageBundle.getInstance().getMessage("error_init_fail", FacesContext.getCurrentInstance().getViewRoot().getLocale());
			FacesMessage facesMessage = new FacesMessage(message);
			FacesContext.getCurrentInstance().addMessage(null, facesMessage);
		}
	}

	private void reset() throws Exception {

		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DAY_OF_YEAR, -3);
		searchFromDate = cal.getTime();
		searchToDate = new Date();
		selectedBuildingId = 0;
		selectedFloorId = 0;
		selectedRoomId = 0;
		selectedMachineId = 0;
		buildingOptions = createBuildingOptions();
		floorOptions = createFloorOptions();
		roomOptions = createRoomOptions();
		machineOptions = createMachineOptions();

		showChart = false;
		lastLocale = Locale.ENGLISH;

	}
	
	public void genSummaryExcel(ActionEvent event) throws Exception {

		boolean valid = true;

		if (selectedBuildingId <= 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(MessageBundle.getInstance().getMessage("building_name", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			sb.append("-");
			sb.append(MessageBundle.getInstance().getMessage("required_field", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			FacesMessage facesMessage = new FacesMessage(sb.toString());
			FacesContext.getCurrentInstance().addMessage("search_building_name", facesMessage);
			valid = false;
		}

		if (selectedFloorId <= 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(MessageBundle.getInstance().getMessage("floor_name", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			sb.append("-");
			sb.append(MessageBundle.getInstance().getMessage("required_field", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			FacesMessage facesMessage = new FacesMessage(sb.toString());
			FacesContext.getCurrentInstance().addMessage("search_floor_name", facesMessage);
			valid = false;
		}

		if (selectedRoomId <= 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(MessageBundle.getInstance().getMessage("room_name", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			sb.append("-");
			sb.append(MessageBundle.getInstance().getMessage("required_field", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			FacesMessage facesMessage = new FacesMessage(sb.toString());
			FacesContext.getCurrentInstance().addMessage("search_room_name", facesMessage);
			valid = false;
		}

		if (selectedMachineId <= 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(MessageBundle.getInstance().getMessage("machine_name", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			sb.append("-");
			sb.append(MessageBundle.getInstance().getMessage("required_field", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			FacesMessage facesMessage = new FacesMessage(sb.toString());
			FacesContext.getCurrentInstance().addMessage("search_machine_name", facesMessage);
			valid = false;
		}

		if (!valid) {
			return;
		}

		StringBuilder sbSearchCriteria = new StringBuilder();

		List<Machine> machineList = new ArrayList<Machine>();
		if (selectedMachineId > 0) {
			Machine machine = maintainService.getMachineById(selectedMachineId);
			machineList.add(machine);

			sbSearchCriteria.append(machine.getRoom().getFloor().getBuilding().getBuildingName());
			sbSearchCriteria.append(", ");
			sbSearchCriteria.append(machine.getRoom().getFloor().getFloorName());
			sbSearchCriteria.append(", ");
			sbSearchCriteria.append(machine.getRoom().getRoomName());
			sbSearchCriteria.append(", ");
			sbSearchCriteria.append(machine.getMachineName());

		}		

		Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
		HSSFWorkbook workbook = auditLogService.getSDataExcelSummaryReport(machineList, sbSearchCriteria.toString(), searchFromDate, searchToDate, locale);

		FacesContext facesContext = FacesContext.getCurrentInstance();
		HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
		response.reset();

		StringBuilder sbHeader = new StringBuilder();
		sbHeader.append("attachment; filename=\"");
		sbHeader.append("TEMP_REPORT_");
		sbHeader.append(DATA_FORMAT.format(new Date()));
		sbHeader.append("_");
		sbHeader.append(".xls\"");

		response.setContentType("application/vnd.ms-excel");
		response.setHeader("Content-Disposition", sbHeader.toString());

		ServletOutputStream out = response.getOutputStream();
		workbook.write(out);
		FacesContext.getCurrentInstance().responseComplete();
	}

	public void genExcel(ActionEvent event) throws Exception {

		boolean valid = true;

		if (selectedBuildingId <= 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(MessageBundle.getInstance().getMessage("building_name", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			sb.append("-");
			sb.append(MessageBundle.getInstance().getMessage("required_field", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			FacesMessage facesMessage = new FacesMessage(sb.toString());
			FacesContext.getCurrentInstance().addMessage("search_building_name", facesMessage);
			valid = false;
		}

		if (selectedFloorId <= 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(MessageBundle.getInstance().getMessage("floor_name", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			sb.append("-");
			sb.append(MessageBundle.getInstance().getMessage("required_field", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			FacesMessage facesMessage = new FacesMessage(sb.toString());
			FacesContext.getCurrentInstance().addMessage("search_floor_name", facesMessage);
			valid = false;
		}

		if (selectedRoomId <= 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(MessageBundle.getInstance().getMessage("room_name", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			sb.append("-");
			sb.append(MessageBundle.getInstance().getMessage("required_field", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			FacesMessage facesMessage = new FacesMessage(sb.toString());
			FacesContext.getCurrentInstance().addMessage("search_room_name", facesMessage);
			valid = false;
		}

		if (selectedMachineId <= 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(MessageBundle.getInstance().getMessage("machine_name", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			sb.append("-");
			sb.append(MessageBundle.getInstance().getMessage("required_field", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			FacesMessage facesMessage = new FacesMessage(sb.toString());
			FacesContext.getCurrentInstance().addMessage("search_machine_name", facesMessage);
			valid = false;
		}

		if (!valid) {
			return;
		}

		StringBuilder sbSearchCriteria = new StringBuilder();

		List<Machine> machineList = new ArrayList<Machine>();
		if (selectedMachineId > 0) {
			Machine machine = maintainService.getMachineById(selectedMachineId);
			machineList.add(machine);

			sbSearchCriteria.append(machine.getRoom().getFloor().getBuilding().getBuildingName());
			sbSearchCriteria.append(", ");
			sbSearchCriteria.append(machine.getRoom().getFloor().getFloorName());
			sbSearchCriteria.append(", ");
			sbSearchCriteria.append(machine.getRoom().getRoomName());
			sbSearchCriteria.append(", ");
			sbSearchCriteria.append(machine.getMachineName());

		}		

		Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
		HSSFWorkbook workbook = auditLogService.getSDataExcelReport(machineList, sbSearchCriteria.toString(), searchFromDate, searchToDate, locale);

		FacesContext facesContext = FacesContext.getCurrentInstance();
		HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
		response.reset();

		StringBuilder sbHeader = new StringBuilder();
		sbHeader.append("attachment; filename=\"");
		sbHeader.append("TEMP_REPORT_");
		sbHeader.append(DATA_FORMAT.format(new Date()));
		sbHeader.append("_");
		sbHeader.append(".xls\"");

		response.setContentType("application/vnd.ms-excel");
		response.setHeader("Content-Disposition", sbHeader.toString());

		ServletOutputStream out = response.getOutputStream();
		workbook.write(out);
		FacesContext.getCurrentInstance().responseComplete();
	}

	public void genChart() throws Exception {

		boolean valid = true;

		if (selectedBuildingId <= 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(MessageBundle.getInstance().getMessage("building_name", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			sb.append("-");
			sb.append(MessageBundle.getInstance().getMessage("required_field", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			FacesMessage facesMessage = new FacesMessage(sb.toString());
			FacesContext.getCurrentInstance().addMessage("search_building_name", facesMessage);
			valid = false;
		}

		if (selectedFloorId <= 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(MessageBundle.getInstance().getMessage("floor_name", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			sb.append("-");
			sb.append(MessageBundle.getInstance().getMessage("required_field", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			FacesMessage facesMessage = new FacesMessage(sb.toString());
			FacesContext.getCurrentInstance().addMessage("search_floor_name", facesMessage);
			valid = false;
		}

		if (selectedRoomId <= 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(MessageBundle.getInstance().getMessage("room_name", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			sb.append("-");
			sb.append(MessageBundle.getInstance().getMessage("required_field", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			FacesMessage facesMessage = new FacesMessage(sb.toString());
			FacesContext.getCurrentInstance().addMessage("search_room_name", facesMessage);
			valid = false;
		}

		if (selectedMachineId <= 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(MessageBundle.getInstance().getMessage("machine_name", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			sb.append("-");
			sb.append(MessageBundle.getInstance().getMessage("required_field", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
			FacesMessage facesMessage = new FacesMessage(sb.toString());
			FacesContext.getCurrentInstance().addMessage("search_machine_name", facesMessage);
			valid = false;
		}

		if (!valid) {
			return;
		}

		if (selectedMachineId > 0) {
			showChart = true;
			if (FacesContext.getCurrentInstance().getViewRoot() != null) {
				lastLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale();

				FacesContext facesContext = FacesContext.getCurrentInstance();
				HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
				response.reset();

				StringBuilder sbHeader = new StringBuilder();
				sbHeader.append("attachment; filename=\"");
				sbHeader.append("TEMP_CHART_");
				sbHeader.append(DATA_FORMAT.format(new Date()));
				sbHeader.append("_");
				sbHeader.append(".jpg\"");

				response.setContentType("image/jpeg");
				response.setHeader("Content-Disposition", sbHeader.toString());

				BufferedImage img = null;
				
				if (showChart) {
					img = auditLogService.getChartBufferedImage(selectedMachineId, searchFromDate, searchToDate, lastLocale);
				}
				
				
				if (img != null) {

					try {
						byte[] buf = new byte[1024];

						File tempFile = File.createTempFile("sdata_chart_image", "jpg");
						ImageIO.write(img, "jpeg", tempFile);

						long length = tempFile.length();
						BufferedInputStream in = new BufferedInputStream(new FileInputStream(tempFile));
						ServletOutputStream out = response.getOutputStream();
						response.setContentLength((int) length);
						while ((in != null) && ((length = in.read(buf)) != -1)) {
							out.write(buf, 0, (int) length);
						}
						out.flush();

						in.close();
						out.close();

						tempFile.delete();
					} catch (Exception ex) {
						logger.error(ex.getMessage());
					}

				} else {
					FacesMessage facesMessage = new FacesMessage(MessageBundle.getInstance().getMessage("error_apply_fail", FacesContext.getCurrentInstance().getViewRoot().getLocale()));
					FacesContext.getCurrentInstance().addMessage(null, facesMessage);

				}
			}
		}

		FacesContext.getCurrentInstance().responseComplete();
	}

	

	public void buildingValueChanged(ValueChangeEvent event) {
		if (null != event.getNewValue()) {
			selectedFloorId = 0;
			selectedRoomId = 0;
			selectedMachineId = 0;
			selectedBuildingId = (Long) event.getNewValue();
			floorOptions = createFloorOptions();
			roomOptions = createRoomOptions();
			machineOptions = createMachineOptions();
		}
	}

	public void floorValueChanged(ValueChangeEvent event) {
		if (null != event.getNewValue()) {
			selectedRoomId = 0;
			selectedMachineId = 0;
			selectedFloorId = (Long) event.getNewValue();
			roomOptions = createRoomOptions();
			machineOptions = createMachineOptions();
		}
	}

	public void roomValueChanged(ValueChangeEvent event) {
		if (null != event.getNewValue()) {
			selectedMachineId = 0;
			selectedRoomId = (Long) event.getNewValue();
			machineOptions = createMachineOptions();
		}
	}

	private List<SelectItem> createBuildingOptions() {
		List<SelectItem> results = new ArrayList<SelectItem>();
		results.add(new SelectItem(0, "------"));
		try {
			List<Building> buildings = maintainService.getAllBuildings(Status.ACTIVE);
			for (Building building : buildings) {
				SelectItem item = new SelectItem(building.getBuildingId(), building.getBuildingName());
				results.add(item);
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
		}

		return results;
	}

	private List<SelectItem> createFloorOptions() {
		selectedFloorId = 0;
		List<SelectItem> results = new ArrayList<SelectItem>();
		results.add(new SelectItem(0, "------"));

		try {
			if (selectedBuildingId > 0) {
				Building selectedBuilding = maintainService.getBuildingById(selectedBuildingId);
				List<Floor> floors = maintainService.getFloors(selectedBuilding, null, Status.ACTIVE);
				for (Floor floor : floors) {
					SelectItem item = new SelectItem(floor.getFloorId(), floor.getFloorName());
					results.add(item);
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		return results;
	}

	private List<SelectItem> createRoomOptions() {
		selectedRoomId = 0;
		List<SelectItem> results = new ArrayList<SelectItem>();
		results.add(new SelectItem(0, "------"));
		try {
			if (selectedFloorId > 0) {
				Floor selectedFloor = maintainService.getFloorById(selectedFloorId);
				List<Room> rooms = maintainService.getRooms(null, selectedFloor, null, Status.ACTIVE);
				for (Room room : rooms) {
					SelectItem item = new SelectItem(room.getRoomId(), room.getRoomName());
					results.add(item);
				}
			}
		} catch (Exception e) {
			logger.error(e.getLocalizedMessage());
		}
		return results;
	}

	private List<SelectItem> createMachineOptions() {
		selectedMachineId = 0;
		List<SelectItem> results = new ArrayList<SelectItem>();
		results.add(new SelectItem(0, "------"));
		try {
			if (selectedRoomId > 0) {
				Room selectedRoom = maintainService.getRoomById(selectedRoomId);
				List<Machine> machines = maintainService.getMachines(null, null, selectedRoom, null, Status.ACTIVE);
				for (Machine machine : machines) {
					SelectItem item = new SelectItem(machine.getMachineId(), machine.getMachineName());
					results.add(item);
				}
			}
		} catch (Exception e) {
			logger.error(e.getLocalizedMessage());
		}
		return results;
	}

	public Date getSearchFromDate() {
		return searchFromDate;
	}

	public void setSearchFromDate(Date searchFromDate) {
		this.searchFromDate = searchFromDate;
	}

	public Date getSearchToDate() {
		return searchToDate;
	}

	public void setSearchToDate(Date searchToDate) {
		this.searchToDate = searchToDate;
	}

	public List<SelectItem> getMachineOptions() {
		return machineOptions;
	}

	public void setMachineOptions(List<SelectItem> machineOptions) {
		this.machineOptions = machineOptions;
	}

	public long getSelectedMachineId() {
		return selectedMachineId;
	}

	public void setSelectedMachineId(long selectedMachineId) {
		this.selectedMachineId = selectedMachineId;
	}

	public List<SelectItem> getBuildingOptions() {
		return buildingOptions;
	}

	public void setBuildingOptions(List<SelectItem> buildingOptions) {
		this.buildingOptions = buildingOptions;
	}

	public List<SelectItem> getFloorOptions() {
		return floorOptions;
	}

	public void setFloorOptions(List<SelectItem> floorOptions) {
		this.floorOptions = floorOptions;
	}

	public List<SelectItem> getRoomOptions() {
		return roomOptions;
	}

	public void setRoomOptions(List<SelectItem> roomOptions) {
		this.roomOptions = roomOptions;
	}

	public long getSelectedBuildingId() {
		return selectedBuildingId;
	}

	public void setSelectedBuildingId(long selectedBuildingId) {
		this.selectedBuildingId = selectedBuildingId;
	}

	public long getSelectedFloorId() {
		return selectedFloorId;
	}

	public void setSelectedFloorId(long selectedFloorId) {
		this.selectedFloorId = selectedFloorId;
	}

	public long getSelectedRoomId() {
		return selectedRoomId;
	}

	public void setSelectedRoomId(long selectedRoomId) {
		this.selectedRoomId = selectedRoomId;
	}

	public boolean isShowChart() {
		return showChart;
	}

	public void setShowChart(boolean showChart) {
		this.showChart = showChart;
	}

	public Locale getLastLocale() {
		return lastLocale;
	}

	public void setLastLocale(Locale lastLocale) {
		this.lastLocale = lastLocale;
	}

}
